((global, factory) => {
    typeof exports === "object" && typeof module !== "undefined"
        ? (module.exports = factory(global))
        : typeof define === "function" && define.amd
            ? define(() => factory(global))
            : ((global = typeof globalThis !== "undefined" ? globalThis : global),
                (global.mfoRef = factory(global)));
})(window, (global) => {
    class Ref {
        #options = {};
        constructor(ops) {
            this.update(ops)
            return this;
        }
        update(ops) {
            const that = this;
            ops && Object.keys(ops).forEach(key => {
                const newVal = Object.assign(Object.assign({}, ops[key]), { value: ops[key].default() })
                if (!that.#options['_' + key]) {
                    that.#options['_' + key] = newVal;
                    Object.defineProperty(that, key, {
                        get() {
                            return that.#options["_" + key].value
                        },
                        set(val) {
                            const item = that.#options["_" + key];
                            if (item.type && typeof item.type() === typeof val) {
                                item.value = val;
                                typeof item.updatedEvent === 'function' && item.updatedEvent();
                            } else {
                                console.error(new Error(`Cannot set type mismatch value for property.(setting '_${key}')`));
                            }
                        }
                    })
                } else {
                    Object.assign(that.#options['_' + key], newVal)
                }
            })
            return this;
        }
        watch(ops) {
            const that = this;
            Object.keys(ops).forEach(key => {
                const item = that.#options['_' + key];
                item.updatedEvent = () => {
                    typeof ops[key] === 'function' && ops[key].call(that, item.value)
                }
            })
            return this;
        }
    }
    return {
        createRef(ops) {
            return new Ref(ops)
        }
    }
})